#title: 复杂的SQL条件
#index:0,1

------------------------------------------------------------------------------------------------------------
概述
	什么是 Nutz.Dao 中的复杂SQL条件
		* 对于 Nutz.Dao 来说，它本质上就是将你的 Java 对象转化成 SQL，然后交给 JDBC 去执行。
		* 而 SQL 中，当执行数据删除和查询操作时，最常用的就是 WHERE 关键字。
		* WHERE 关键字后面的就是所谓的复杂查询条件
	Nutz.Dao 将如何如何使用这个条件
		* Dao 接口的 clear 方法和 query 方法的第二个参数，就是为了生成 WHERE 后面那段字符串设计的
		* 这个参数是一个 org.nutz.dao.Condition 接口的实现类
		* 通过该接口的 toSql(org.nutz.dao.entity.Entity) 方法， Nutz.Dao 将获得 WHERE 后面那段字符串
		* 当然也包括 ORDER BY
------------------------------------------------------------------------------------------------------------
Condition 接口
	* 这个接口只有一个方法` toSql(Entity<?> entity)`
		* 这个方法带一个参数 org.nutz.dao.entity.Entity
		* 通过这个参数，实现者可以获得当前需要操作的实体的配置信息
		* 当然，如果你不需要的话，你可以不理睬这个参数
	* Nutz.Dao 会将`toSql(Entity<?> entity)` 的返回直接拼接到SQL 的 WHERE 关键字后面
		* 如果你返回的字符串以 WHERE 或者 ORDER BY 开头，它会直接使用，否则会补上一个 WHERE 关键字
		* 这个判断会忽略前后空白以及大小写
------------------------------------------------------------------------------------------------------------
Nutz 给你的快速实现
	* 如果你的数据库字段被假设不会发生变化，用直接硬编码是个很好的选择
	* 如果在开发期，你的数据库字段变化非常频繁，用 Cnd 工具类则是更好的选择

	一个友好的工具类 -- Cnd
	
		有些情况，数据库中的字段同 Java 对象中的字段并不同名，
        所以就需要给 Java 字段上的数据库字段注解加上参数 @Column({#F0F;"数据库字段名"})
		如果你通过 Cnd.wrap() 硬编码某个字段，那么当这个字段数据库字段名发生改变时，你就需要改动很多。
		因此你希望仅仅将对于数据库的变动限制在 Java 对象的源文件里
		所以 Nutz 提供了 Cnd.where() 方法
		{{{<Java>
		Condition c = Cnd.where("age",">",30).and("name", "LIKE", "%K%").asc("name").desc("id");
		}}}
		这个条件将生成 SQL 
		{{{<SQL>
		WHERE age>30 AND name LIKE '%K%' ORDERBY name ASC, id DESC
		}}}
		你也可以嵌套表达式
		{{{<JAVA>
		SqlExpressionGroup e1 = Cnd.exps("name", "LIKE", "P%").and("age", ">", "20");
		SqlExpressionGroup e2 = Cnd.exps("name", "LIKE", "S%").and("age", "<", "30");
		Condition c = Cnd.where(e1).or(e2).asc("name");
		}}}
		这个条件将生成 SQL 
		{{{<SQL>
		WHERE (name LIKE 'P%' AND age>'20') OR (name LIKE 'S%' AND age<'30') ORDER BY name ASC
		}}}

	直接硬编码(不推荐)
	
		最暴力的方法就是直接输出 WHERE 关键字后面的 SQL 代码了。比如查询一个 Person 对象
		{{{<JAVA>
		List<Person> crowd = dao.query(Person.class, Cnd.wrap("name LIKE 'J%' AND age>20"), null);
		}}}
		
		部分暴力,使用Static
		
		{{{<JAVA>
		// 筛选年龄(age)小于20,现金(cash字段)多于负债(due字段)的XX
		List<Pet> list = dao.query(Girl.class, Cnd.where("age", "<", 20).and(new Static("cash > due")));
		}}}

------------------------------------------------------------------------------------------------------------
拼装更加复杂的条件
    
    上面的例子的 Cnd.where 函数，在大多数情况下可以快速的生成一个简单的查询条件。但是，如果查询条件非常复杂，
    用它可能就比较费劲了。是的，它的设计初衷就是 "{#080;* 查询条件应该一行搞定}"。

    有些时候，查询条件很复杂，一行确实搞不定，怎么办？{* Nutz-1.b.38} 以后，提供了 Criteria 接口，它继承自
    Condition 接口，它的设计目的有两个：
     # 让程序员更容易的拼装复杂逻辑的条件
     # 让生成的 SQL 可以被参数化，更好的支持 PreparedStatement

    这个接口的使用也很简单，它基本符合 "IDE 的所见即所得" 接口设计原则。 就是说，如果你的 IDE 有智能提示的话，
    你使用这个接口是不需要文档的。

    {{{<JAVA>
    // 创建一个 Criteria 接口实例
    Criteria cri = Cnd.cri();

    // 组装条件
    if(...){
        cri.where().andIn("id", 3,4,5).andIn("name", "Peter", "Wendal", "Juqkai");
    }else if(...){
        cri.where().andLT("id", 9);
    }

    if(...){
        cri.where().andLike("name", "%A%");
    }

    cri.getOrderBy().asc("name").desc("id");

    // 执行查询
    List<MyObj> list = dao.query(MyObj.class, cri, null);
    }}}

    Criteria 的 where() 函数返回的是 SqlExpressionGroup，主要由它来提供各种 SQL 条件的组合方法。
    这里需要给出一点提示，比如方法名 {#080;* andGT}，表示的是 and{#080;*G}reat{#080;*T}han，即
    "{#080;*大于}" 的意思，同理:
     * LT : 小于 (LessThan)
     * GTE : 大于等于 (GreatThanEqual)
     * LTE : 小于等于 (LessThanEqual)

------------------------------------------------------------------------------------------
模糊查询的小提示

	如下代码,当str的长度大于1和等于1时的行为有差异
	
	{{{<JAVA>
	Cnd cnd = Cnd.where("name", "like", str);
	// 若str的长度为1,输出的SQL是
	// where name like "%a%"
	// 若str的长度为2,输出的SQL是
	// where name like "ab"
	}}}
	
	正确的写法是
	
	{{{<JAVA>
	Cnd cnd = Cnd.where("name", "like", "%" + str + "%s");
	}}}














